#include "LedCtrl.h"     // 包含LED控制相关头文件
#include "tim.h"         // 包含定时器相关头文件
#include "KEY.h"         // 包含按键相关头文件
#include "main.h"        // 包含主程序相关头文件
#include "math.h"        // 添加头文件以支持数学函数（用于pow函数）
#include "TOF.h"  
#include <stdlib.h>  // 添加stdlib.h头文件以支持abs函数
// 全局LED参数结构体实例化
LEDParameter LEDParameterSET;

// 全局变量定义 - 用于距离检测和亮度渐变控制
static uint16_t lastDistance = 380;       // 上一次检测的距离 (38cm)
static uint16_t targetDistance = 380;     // 目标距离 (38cm)
static uint32_t stableStartTime = 0;      // 开始稳定的起始时间
static uint8_t isStabilizing = 0;         // 是否处于稳定检测中（0：否，1：是）
static uint8_t isFading = 0;              // 是否处于亮度渐变过程中（0：否，1：是）
static float currentRatio = 0.5f;         // 当前亮度比例（0.0-1.0）
static float targetRatio = 0.5f;          // 目标亮度比例（0.0-1.0）
static float startRatio = 0.5f;           // 渐变开始时的亮度比例
static uint32_t fadeStartTime = 0;        // 渐变开始的系统时间戳

// 新增：累积变化检测变量
static float accumulatedBrightnessChange = 0.0f;  // 累积亮度变化
static uint32_t lastSignificantChangeTime = 0;  // 上次显著变化时间


// 参数配置
#define FADE_DURATION_MS 1500                // 渐变持续时间（毫秒）- 0.8秒，原来2000ms
#define STABLE_DURATION_MS 100              // 稳定期持续时间（毫秒）- 0.1秒，原来200ms
#define DISTANCE_CHANGE_THRESHOLD 6         // 距离变化阈值（mm）- 从5mm增加到6mm
#define BRIGHTNESS_CHANGE_THRESHOLD 0.03f   // 亮度变化阈值（3%）- 从2%增加到3%
#define ACCUMULATED_CHANGE_THRESHOLD 0.06f  // 累积变化阈值（6%）- 从5%增加到6%
#define MAX_NO_CHANGE_DURATION 1500         // 最大无变化时间（ms）- 从2000ms减少到1500ms

// 亮度等级数组定义
extern int MAIN_4000_LED_levels[NUM_LED_LEVELS] = {0, 400, 600, 1100};//5000K亮度等级，重装载值为2999
extern int MAIN_5000_LED_levels[NUM_LED_LEVELS] = {0, 400, 600, 1100};//4000K亮度等级，重装载值为2999

/**
 * @brief 二次缓入缓出函数
 */
float easeInOutQuad(float t) {
    return t < 0.5f ? 2.0f * t * t : 1.0f - pow(-2.0f * t + 2.0f, 2.0f) / 2.0f;
}

// 1. 修改缓动函数为线性渐变
/**
 * @brief 线性渐变函数 - 替代二次缓入缓出
 */
float linearTween(float t) {
    return t;  // 简单的线性映射
}

/**
 * @brief 亮度渐变函数 
 */
void fadeToTargetRatio(void)
{
    if (isFading)  // 检查是否处于渐变过程中
    {
        uint32_t currentTime = HAL_GetTick();  // 获取当前系统时间
        uint32_t elapsedTime = currentTime - fadeStartTime;  // 计算已流逝的渐变时间
        
        if (elapsedTime >= FADE_DURATION_MS)  // 检查渐变是否结束
        {
            currentRatio = targetRatio;  // 直接设置为目标亮度比例
            isFading = 0;  // 结束渐变过程
        }
        else  // 渐变仍在进行中
        {
            float progress = (float)elapsedTime / FADE_DURATION_MS;  // 计算渐变进度(0.0-1.0)
            float easedProgress = linearTween(progress);  // 使用线性渐变函数处理进度
            currentRatio = startRatio + (targetRatio - startRatio) * easedProgress;  // 计算当前亮度比例
        }
    }
}

/**
 * @brief 应用亮度比率到PWM - 修改版（实际设置PWM值）
 */
void applyBrightnessRatio(void)
{
    int mainLevel = 0;
    switch (DeviceStatus.currentMode)
    {
        case 1: // 4000k模式
            mainLevel = MAIN_4000_LED_levels[DeviceStatus.currentLevel];
            // 实际设置PWM值
            __HAL_TIM_SetCompare(&Main_4k_tim, Main_4k_CHANNEL, (int)(mainLevel * currentRatio * LEDParameterSET.LEDRATIO));
            break;
        case 0: // 5000k模式
            mainLevel = MAIN_5000_LED_levels[DeviceStatus.currentLevel];
            // 实际设置PWM值
            __HAL_TIM_SetCompare(&Main_5k_tim, Main_5k_CHANNEL, (int)(mainLevel * currentRatio * LEDParameterSET.LEDRATIO));
            break;
    }
}

/**
 * @brief LED主控制函数 - 增强版稳定期检测
 */
void LEDChange(void)
{
    // 电源关闭状态处理
    if (DeviceStatus.powerState == 0)
    {
        DeviceStatus.pendingMode = 1;
        MAIN_4000_off;
        MAIN_5000_off;
        WORKPOWER_OFF;
        
        // 重置所有状态变量
        lastDistance = 350;
        targetDistance = 350;
        stableStartTime = 0;
        isStabilizing = 0;
        isFading = 0;
        currentRatio = 0.5f;
        targetRatio = 0.5f;
        startRatio = 0.5f;
        accumulatedBrightnessChange = 0.0f;
        lastSignificantChangeTime = 0;
    }
    // 电源开启状态处理
    else if (DeviceStatus.powerState == 1)
    {
        WORKPOWER_ON;
        
        // 检查模式或亮度等级变化
        if (DeviceStatus.currentMode != DeviceStatus.pendingMode || 
            DeviceStatus.currentLevel != DeviceStatus.pendingLevel)
        {
            DeviceStatus.currentMode = DeviceStatus.pendingMode;
            DeviceStatus.currentLevel = DeviceStatus.pendingLevel;
        }
        
        // 获取当前距离传感器值
        uint16_t distance = demo_run();
        
        // 限制距离范围
        if(distance > 500) distance = 500;
        if(distance < 380) distance = 380;
        
        // 计算当前距离与上次检测距离的差值
        int16_t distanceDiff = distance - lastDistance;
        
        // 1. 显著距离变化检测机制（快速响应策略）
        // 当距离变化超过设定阈值(DISTANCE_CHANGE_THRESHOLD=6mm)时，立即响应
        if (abs(distanceDiff) > DISTANCE_CHANGE_THRESHOLD)
        {
            targetDistance = distance;            // 更新目标距离
            stableStartTime = HAL_GetTick();      // 记录稳定期起始时间
            isStabilizing = 1;                    // 进入稳定检测状态
            accumulatedBrightnessChange = 0.0f;   // 重置累积变化量
            lastSignificantChangeTime = HAL_GetTick(); // 更新上次显著变化时间
        }
        // 2. 微小变化累积检测机制（渐变响应策略）
        // 当距离有微小变化但未达到显著阈值时，累积这些变化
        else if (abs(distanceDiff) > 0)
        {
            // 将微小距离变化转换为对应的亮度变化比例
            // 公式解析：distanceDiff/120.0f将距离变化映射到[0,1]区间，再乘以0.52f(最大亮度变化范围)
            float microBrightnessChange = ((float)distanceDiff / 120.0f * 0.52f);
            // 只累加变化量的绝对值
            accumulatedBrightnessChange += fabs(microBrightnessChange);
            
            // 当累积的微小变化超过设定阈值(ACCUMULATED_CHANGE_THRESHOLD=6%)时触发亮度调整
            if (accumulatedBrightnessChange > ACCUMULATED_CHANGE_THRESHOLD)
            {
                targetDistance = distance;            // 更新目标距离
                stableStartTime = HAL_GetTick();      // 记录稳定期起始时间
                isStabilizing = 1;                    // 进入稳定检测状态
                accumulatedBrightnessChange = 0.0f;   // 重置累积变化量
                lastSignificantChangeTime = HAL_GetTick(); // 更新上次显著变化时间
            }
        }
        
        // 3. 时间阈值验证机制（长时间无变化处理）
        uint32_t currentTime = HAL_GetTick();
        // 如果长时间(MAX_NO_CHANGE_DURATION=1500ms)没有显著变化且不在稳定期
        if ((currentTime - lastSignificantChangeTime) > MAX_NO_CHANGE_DURATION && !isStabilizing)
        {
            // 检查当前距离与目标距离是否有小差异
            if (abs(distance - targetDistance) > 2) // 允许2mm的误差范围
            {
                targetDistance = distance;            // 更新目标距离
                stableStartTime = currentTime;        // 记录稳定期起始时间
                isStabilizing = 1;                    // 进入稳定检测状态
                accumulatedBrightnessChange = 0.0f;   // 重置累积变化量
            }
            lastSignificantChangeTime = currentTime;  // 更新检查时间点
        }
        
        // 保存本次检测的距离值作为下次比较的基准
        lastDistance = distance;
        
        // 稳定期处理和亮度变化验证
        if (isStabilizing)
        {
            // 计算已处于稳定期的时间
            uint32_t stableElapsedTime = currentTime - stableStartTime;
            
            // 当稳定期达到设定时间(STABLE_DURATION_MS=100ms)时，认为距离稳定
            if (stableElapsedTime >= STABLE_DURATION_MS)
            {
                // 计算稳定后的目标亮度比例
                // 算法解析：
                // - 0.48f是基础亮度(最小亮度)
                // - (targetDistance - 380)计算距离偏移量(380mm是起始距离)
                // - /120.0f将距离范围(380-500mm)归一化到[0,1]区间
                // - *0.52f将距离变化映射到可用亮度变化范围(0.48f-1.0f)
                float newTargetRatio = 0.48f + ((targetDistance - 380) / 120.0f * 0.52f);
                
                // 亮度变化验证：只有当变化量超过阈值(BRIGHTNESS_CHANGE_THRESHOLD=3%)时才执行渐变
                // 这可以避免微小的亮度抖动，提高稳定性和用户体验
                if (fabs(currentRatio - newTargetRatio) > BRIGHTNESS_CHANGE_THRESHOLD)
                {
                    startRatio = currentRatio;      // 记录渐变开始时的亮度比例
                    targetRatio = newTargetRatio;   // 设置目标亮度比例
                    fadeStartTime = currentTime;    // 记录渐变开始时间
                    isFading = 1;                   // 激活渐变标志
                }
                
                // 重置稳定状态标志和累积变化量
                isStabilizing = 0;
                accumulatedBrightnessChange = 0.0f;
            }
        }
        
        // 执行渐变更新亮度比例
        fadeToTargetRatio();
        
        // 应用当前计算的亮度比率到PWM
        applyBrightnessRatio();
        
        // 模式切换时的LED开关控制
        switch (DeviceStatus.currentMode)
        {
            case 1: // 4000k色温开
            
                MAIN_4000_on;
                MAIN_5000_off;
                break;
            case 0: // 5000k色温开
           
                MAIN_4000_off;
                MAIN_5000_on;
                break;
        }
    }
}